package com.flexdms.i18n;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public abstract class BaseTranslator implements Translator
{

	Locale sourceLocale;
	

	public Locale getSourceLocale()
	{
		return sourceLocale;
	}

	public void setSourceLocale(Locale sourceLocale)
	{
		this.sourceLocale = sourceLocale;
	}

	public boolean isSameLocale(Locale locale)
	{
		if (locale.getLanguage().equalsIgnoreCase(sourceLocale.getLanguage()))
		{
			return true;
		}
		if (locale.getLanguage()=="")
		{
			return true;
		}
		return false;
	}

	@Override
	public String translate(String key, Locale locale) throws Exception
	{
		if (isSameLocale(locale))
		{
			return key;
		}
		if (key==null || key.length()==0)
		{
			return "";
		}
		if (isMessageFormat(key))
		{
			List<String> qStrings=extractStaticText(key);
			List<String> translationList=_translate(qStrings, locale);
			return reconstructMessage(translationList, key);
			
		} else {
			List<String> qStrings = new ArrayList<String>();
			qStrings.add(key);
			return _translate(qStrings, locale).get(0);
		}
		
	}
	
	@Override
	public List<String> translate(List<String> qStrings, Locale locale)
			throws Exception
	{
		if (isSameLocale(locale))
		{
			return qStrings;
		}
		List<ListForSingleMessage> formats=new ArrayList<ListForSingleMessage>();
		List<String> transformedList=new ArrayList<String>(qStrings.size()*2);
		
		
		for(String msg:qStrings)
		{
			if (isMessageFormat(msg))
			{
				ListForSingleMessage singleMessage=new ListForSingleMessage(msg);
				singleMessage.setStartIndex(transformedList.size());
				transformedList.addAll(singleMessage.getSrcList());
				formats.add(singleMessage);
			} else {
				transformedList.add(msg);
			}
		}
		List<String> translated=_translate(transformedList, locale);
		List<String> resultsList=new ArrayList<String>(qStrings.size());
		int preend=0;
		for(ListForSingleMessage singleMessage: formats)
		{
			resultsList.addAll(translated.subList(preend, singleMessage.getStartIndex()));
			resultsList.add(singleMessage.reconstruct(translated));
			preend=singleMessage.getStartIndex()+singleMessage.getLen();
		}
		
		resultsList.addAll(translated.subList(preend, translated.size()));
		
		return resultsList;
	}
	
	protected abstract List<String> _translate(List<String> qStrings, Locale locale)
			throws Exception;
	

	static Pattern pattern=Pattern.compile("\\{\\d+([^\\}]+)?\\}");
	public static boolean isMessageFormat(String msg)
	{
		Matcher m = pattern.matcher(msg);
		if (m.find())
		{
			return true;
		} else {
			return false;
		}
	}
	
	public static List<String> extractStaticText(String msg)
	{
		Matcher m = pattern.matcher(msg);
		List<String> staticText = new ArrayList<String>(5);
		int preend = 0;
		while (m.find())
		{
			if (msg.substring(preend, m.start()).length() > 0)
			{
				staticText.add(msg.substring(preend, m.start()));
			}
			preend = m.end();
		}
		if (msg.substring(preend).length() > 0)
		{
			staticText.add(msg.substring(preend));
		}
		return staticText;
	}

	public static String reconstructMessage(List<String> translation, String msg)
	{
		Matcher m = pattern.matcher(msg);
		StringBuilder sbBuilder = new StringBuilder();
		int preend = 0;
		int count = 0;
		while (m.find())
		{
			if (msg.substring(preend, m.start()).length() > 0)
			{
				sbBuilder.append(translation.get(count));
				count++;
			}
			sbBuilder.append(msg.substring(m.start(), m.end()));
			preend = m.end();
		}
		if (msg.substring(preend).length() > 0)
		{
			sbBuilder.append(translation.get(count));
		}
		return sbBuilder.toString();
	}
	
	public static class ListForSingleMessage
	{
		String msg;
		List<String> srcList;
		int startIndex;
		int len;
		
		public ListForSingleMessage(String msg)
		{
			super();
			this.msg = msg;
		}
		public List<String> getSrcList()
		{
			List<String> retList=extractStaticText(msg);
			len=retList.size();
			return retList;
		}
		public int getStartIndex()
		{
			return startIndex;
		}
		public void setStartIndex(int startIndex)
		{
			this.startIndex = startIndex;
		}
		public int getLen()
		{
			return len;
		}
		
		public String reconstruct(List<String> translated)
		{
			return reconstructMessage(translated.subList(startIndex, startIndex+len), msg);
		}
		
		
		
		
	}
	
}
